package com.zbs.framework.common.utils.mp;

import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @author: Zbs
 * @createTime: 2020/12/18 14:54
 * 做一些非空判断，使业务代码块更加简洁
 */

@Getter
@Setter
public class MpQueryWrapper<T> extends LambdaQueryWrapper<T> {

    private BaseMapper<T> baseMapper;
//    private List<String> sqlSelectList = new ArrayList<>();
    private SharedString sqlSelect = new SharedString();
    public MpQueryWrapper(BaseMapper<T> baseMapper) {
        this.baseMapper = baseMapper;
    }

    @Override
    public String getSqlSelect() {
        String superSqlSelect = super.getSqlSelect();
        if (StringUtils.hasLength(superSqlSelect)) {
            return superSqlSelect;
        }
        return sqlSelect.getStringValue();
    }

    @Override
    public void clear() {
        super.clear();
        this.sqlSelect.toNull();
    }

    public Page<T> page(Integer pageIndex, Integer pageSize) {
        Page<T> page = PageUtil.page(pageIndex, pageSize);
        return baseMapper.selectPage(page,super.typedThis);
    }

    public Page<T> page(Integer pageIndex, Integer pageSize,boolean searchCount) {
        Page<T> page = PageUtil.page(pageIndex, pageSize);
        page.setSearchCount(searchCount);
        return baseMapper.selectPage(page,super.typedThis);
    }

    public Page<T> page(Page<T> page) {
        return baseMapper.selectPage(page,super.typedThis);
    }


    public List<T> list() {
        return baseMapper.selectList(super.typedThis);
    }


    public T getOne() {
        return baseMapper.selectOne(super.typedThis);
    }


    public Long count() {
        return baseMapper.selectCount(super.typedThis);
    }


    @SafeVarargs
    public final MpQueryWrapper<T> selectColumns(SFunction<T, ?>... columns) {
        if (columns != null && columns.length > 0) {
//            this.sqlSelectList.addAll(columnsToStringV2(Arrays.asList(columns)));
            super.select(columns);
        }
        return this;
    }

//    protected final List<String> columnsToStringV2(List<SFunction<T, ?>> columns) {
//        return columns
//                .stream()
//                .map(i -> columnToString(i, true))
//                .collect(Collectors.toList());
//    }
//
//    public MpQueryWrapper<T> selectColumns(String ... columns) {
//        if (columns != null && columns.length > 0) {
//            this.sqlSelectList.addAll(Arrays.asList(columns));
//        }
//        return this;
//    }


    public MpQueryWrapper<T> selectColumns(List<String> columns) {
        if (!CollectionUtils.isEmpty(columns)) {
            this.sqlSelect.setStringValue(String.join(StringPool.COMMA, columns));
        }
        return this;
    }

    public MpQueryWrapper<T> selectColumns(String... columns) {
        if (columns != null && columns.length > 0) {
            this.sqlSelect.setStringValue(String.join(StringPool.COMMA, columns));
        }
        return this;
    }


    /**
     * 等于 =
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> eq(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.eq(column, val);
        }
        return this;
    }
    /**
     * 等于 =
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> eq(boolean condition,SFunction<T, ?> column, Object val) {
        super.eq(condition,column, val);
        return this;
    }

    /**
     * 不等于 <>
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> ne(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.ne(column, val);
        }
        return this;
    }
    public MpQueryWrapper<T> ne(boolean condition,SFunction<T, ?> column, Object val) {
        super.ne(condition,column, val);
        return this;
    }

    /**
     * 大于 >
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> gt(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.gt(column, val);
        }
        return this;
    }

    /**
     * 大于 >
     * @param column 字段
     * @param sql sql
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> gtSql(SFunction<T, ?> column, String sql) {
        if (!ObjectUtils.isEmpty(sql)) {
            super.gtSql(column, sql);
        }
        return this;
    }

    /**
     * 大于等于 >=
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> ge(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.ge(column, val);
        }
        return this;
    }

    /**
     * 大于等于 >=
     *
     * @param column 字段
     * @param sql    sql
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> geSql(SFunction<T, ?> column, String sql) {
        if (!ObjectUtils.isEmpty(sql)) {
            super.geSql(column, sql);
        }
        return this;
    }

    /**
     * 小于 <
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> lt(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.lt(column, val);
        }
        return this;
    }

    /**
     * 小于 <
     *
     * @param column 字段
     * @param sql    sql
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> ltSql(SFunction<T, ?> column, String sql) {
        if (!ObjectUtils.isEmpty(sql)) {
            super.ltSql(column, sql);
        }
        return this;
    }

    /**
     * 小于等于 <=
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> le(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.le(column, val);
        }
        return this;
    }

    /**
     * 小于等于 <=
     *
     * @param column 字段
     * @param sql    sql
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> leSql(SFunction<T, ?> column, String sql) {
        if (!ObjectUtils.isEmpty(sql)) {
            super.leSql(column, sql);
        }
        return this;
    }

    public MpQueryWrapper<T> like(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.like(column, val);
        }
        return this;
    }

    public MpQueryWrapper<T> notLike(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.notLike(column, val);
        }
        return this;
    }

    /**
     * LIKE '%值'
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> likeLeft(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.likeLeft(column, val);
        }
        return this;
    }

    /**
     * LIKE '值%'
     *
     * @param column 字段
     * @param val    值
     * @return MpQueryWrapper
     */
    public MpQueryWrapper<T> likeRight(SFunction<T, ?> column, Object val) {
        if (!ObjectUtils.isEmpty(val)) {
            super.likeRight(column, val);
        }
        return this;
    }

    public MpQueryWrapper<T> between(SFunction<T, ?> column, Object val1, Object val2) {
        super.between(column, val1, val2);
        return this;
    }

    public MpQueryWrapper<T> or(Consumer<LambdaQueryWrapper<T>> consumer) {
        super.or(consumer);
        return this;
    }

    public MpQueryWrapper<T> and(Consumer<LambdaQueryWrapper<T>> consumer) {
        super.and(consumer);
        return this;
    }

    public MpQueryWrapper<T> notBetween(SFunction<T, ?> column, Object val1, Object val2) {
        super.notBetween(column, val1, val2);
        return this;
    }

    public MpQueryWrapper<T> isNull(SFunction<T, ?> column) {
        super.isNull(column);
        return this;
    }

    public MpQueryWrapper<T> isNotNull(SFunction<T, ?> column) {
        super.isNotNull(column);
        return this;
    }

    public MpQueryWrapper<T> in(SFunction<T, ?> column, Object... values) {
        if (values != null && values.length > 0) {
            super.in(column, values);
        }
        return this;
    }
    public MpQueryWrapper<T> in(boolean condition,SFunction<T, ?> column, Object... values) {
        super.in(condition,column, values);
        return this;
    }

    public MpQueryWrapper<T> in(SFunction<T, ?> column, Collection<?> coll) {
        if (!CollectionUtils.isEmpty(coll)) {
            super.in(column, coll);
        }
        return this;
    }

    public MpQueryWrapper<T> inSql(SFunction<T, ?> column, String sql) {
        if (StringUtils.hasLength(sql)) {
            super.inSql(column, sql);
        }
        return this;
    }

    public MpQueryWrapper<T> notInSql(SFunction<T, ?> column, String sql) {
        if (StringUtils.hasLength(sql)) {
            super.notInSql(column, sql);
        }
        return this;
    }

    public MpQueryWrapper<T> notIn(SFunction<T, ?> column, Object... values) {
        if (values != null && values.length > 0) {
            super.notIn(column, values);
        }
        return this;
    }

    public MpQueryWrapper<T> notIn(SFunction<T, ?> column, Collection<?> coll) {
        if (!CollectionUtils.isEmpty(coll)) {
            super.notIn(column, coll);
        }
        return this;
    }

    @SafeVarargs
    public final MpQueryWrapper<T> groupByColumn(SFunction<T, ?>... column) {
        super.groupBy(Arrays.asList(column));
        return this;
    }

    @SafeVarargs
    public final MpQueryWrapper<T> orderByAscColumn(SFunction<T, ?>... column) {
        super.orderByAsc(Arrays.asList(column));
        return this;
    }


    @SafeVarargs
    public final MpQueryWrapper<T> orderByDescColumn(SFunction<T, ?>... column) {
        super.orderByDesc(Arrays.asList(column));
        return this;
    }


    public MpQueryWrapper<T> having(String sqlHaving, Object... params) {
        super.having(sqlHaving, params);
        return this;
    }

    public MpQueryWrapper<T> func(Consumer<LambdaQueryWrapper<T>> consumer) {
        super.func(consumer);
        return this;
    }

    public boolean exists() {
        return this.baseMapper.exists(super.typedThis);
    }

    public MpQueryWrapper<T> exists(String existsSql) {
        super.exists(existsSql);
        return this;
    }

    public MpQueryWrapper<T> exists(String existsSql, Object... values) {
        if (values.length > 0) {
            super.exists(existsSql, values);
        }
        return this;
    }


    public MpQueryWrapper<T> notExists(String existsSql) {
        super.notExists(existsSql);
        return this;
    }

    public MpQueryWrapper<T> notExists(String existsSql, Object... values) {
        if (values.length > 0) {
            super.notExists(existsSql, values);
        }
        return this;
    }

    public MpQueryWrapper<T> last(String lastSql) {
        if (StringUtils.hasLength(lastSql)) {
            super.last(lastSql);
        }
        return this;
    }
}
